package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.mapper.EmpMapper;
import com.itheima.pojo.*;
import com.itheima.service.DeptService;
import com.itheima.service.EmpExprService;
import com.itheima.service.EmpService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class EmpServiceImpl extends ServiceImpl<EmpMapper, Emp> implements EmpService {
    @Autowired
    private DeptService deptService;
    @Autowired
    private EmpExprService empExprService;

    /**
     * 分页查询
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<Emp> getpageResult(EmpQueryParam param) {

        Page<Emp> page = new Page<>(param.getPage(), param.getPageSize());

        // 根据最后修改时间倒序排序
        page.addOrder(OrderItem.desc("update_time"));

        // 构建查询条件

        /*
        LambdaQueryWrapper 类：
        LambdaQueryWrapper 是 MyBatis-Plus 提供的一个用于构建查询条件的类。
        它允许使用 Lambda 表达式来避免硬编码字段名，从而提高代码的可读性和安全性。
        泛型参数 Emp：
        LambdaQueryWrapper<Emp> 表示这个查询条件包装器是针对 Emp 实体类的。
        Emp 是一个实体类，通常对应数据库中的一张表。
        实例化：
        new LambdaQueryWrapper<>() 创建了一个 LambdaQueryWrapper 的实例。
        这个实例可以用来构建复杂的查询条件，例如等值查询、范围查询、模糊查询等。
      */
        LambdaQueryWrapper<Emp> queryWrapper = new LambdaQueryWrapper<>();

        // 根据条件查询
        queryWrapper.like(param.getName() != null && !param.getName().isEmpty(), Emp::getName, param.getName())
                .eq(param.getGender() != null, Emp::getGender, param.getGender())
                .between(param.getBegin() != null && param.getEnd() != null, Emp::getEntryDate, param.getBegin(), param.getEnd());


        //调用page方法完成分页查询
        page = page(page, queryWrapper);

        // 获取员工集合
        List<Emp> emps = page.getRecords();

        // 获取所有员工的部门id
        /**
         *
         1.emps.stream():
         emps 是一个 List<Emp> 类型的集合，其中 Emp 是一个实体类。
         stream() 方法将 emps 集合转换为一个流（Stream），流是一种支持顺序和并行聚合操作的高级抽象。
         2. .map(emp -> emp.getDeptId()):
         map 是流的一个中间操作，用于对流中的每个元素执行指定的操作并返回一个新的流。
         3. emp -> emp.getDeptId() 是一个 Lambda 表达式，表示对流中的每个 Emp 对象调用 getDeptId() 方法，获取其 deptId 属性。
         因此，map 操作将 emps 流中的每个 Emp 对象映射为其 deptId 属性，生成一个新的流 Stream<Long>。
         4. .collect(Collectors.toList()):
         collect 是流的一个终端操作，用于将流中的元素收集到一个集合中。
         Collectors.toList() 是一个收集器（Collector），用于将流中的元素收集到一个 List 中。
         因此，collect(Collectors.toList()) 将 Stream<Long> 中的所有元素收集到一个 List<Long> 中。

         */
        List<Long> deptIds = emps.stream().map(emp -> emp.getDeptId()).collect(Collectors.toList());
        // 批量查询这些部门的信息
        List<Dept> depts = deptService.listByIds(deptIds);
        // 将部门名称封装到员工对象中
        emps.forEach(emp -> {
            depts.forEach(dept -> {
                if (emp.getDeptId() != null && emp.getDeptId().equals(dept.getId())) {
                    emp.setDeptName(dept.getName());
                }
            });

        });


        return new PageResult<>(page.getTotal(), emps);


    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveEmp(Emp emp) {
        emp.setCreateTime(LocalDateTime.now());
        emp.setUpdateTime(LocalDateTime.now());

        save(emp);


        // 调用service层方法保存员工工作经历信息
        List<EmpExpr> exprList = emp.getExprList();

        // 添加工作经历所属员工
        exprList.forEach(expr -> expr.setEmpId(emp.getId()));

        empExprService.saveBatch(exprList);


    }

    @Override
    public Emp getEmpById(Integer id) {

         Emp emp = getById(id);
        emp.setExprList(empExprService.list(new LambdaQueryWrapper<EmpExpr>().eq(EmpExpr::getEmpId, id)));
        return emp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEmp(Emp emp) {
         emp.setUpdateTime(LocalDateTime.now());
         updateById(emp);

        empExprService.remove(new LambdaQueryWrapper<EmpExpr>().eq(EmpExpr::getEmpId, emp.getId()));

        List<EmpExpr> exprList = emp.getExprList();
        /*

        exprList.forEach(...):
        exprList 是一个 List<EmpExpr> 类型的集合，包含多个 EmpExpr 对象。
        forEach 方法是 Java 8 引入的 Stream API 方法，用于对集合中的每个元素执行指定的操作。
        Lambda 表达式 expr -> expr.setEmpId(emp.getId()):
        expr 是 exprList 中的每一个 EmpExpr 对象。
        expr.setEmpId(emp.getId()) 是对每个 EmpExpr 对象执行的操作，即将当前 emp 对象的 id 设置到 EmpExpr 对象的 empId 字段中。
         */


        if (exprList != null && !exprList.isEmpty()) {
            exprList.forEach(expr -> expr.setEmpId(emp.getId()));
        }
        empExprService.saveBatch(exprList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeEmpByIds(List<Integer> ids) {
         removeBatchByIds(ids);
         empExprService.remove(new LambdaQueryWrapper<EmpExpr>().in(EmpExpr::getEmpId, ids));



    }


}
